home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 6647 / 6647.xpi / chrome / httpfox.jar / content / HttpFox.js < prev    next >
Text File  |  2009-04-10  |  37KB  |  1,246 lines

  1. /*
  2.     HttpFox - An HTTP analyzer addon for Firefox
  3.     Copyright (C) 2008 Martin Theimer
  4.     
  5.     This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation; either version 2 of the License, or
  8.     (at your option) any later version.
  9.     
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.     
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19.  
  20. // HttpFoxController
  21. function HttpFoxController()
  22. {
  23.     this.init();
  24. }
  25. HttpFoxController.prototype =
  26. {
  27.     HttpFoxService: null,
  28.     
  29.     RequestTree: null,
  30.     
  31.     SelectedRequestDetailsTab: null,
  32.     
  33.     IntervalChecker: null,
  34.     
  35.     QuickFilterText: "",
  36.     
  37.     FilteredRequests: null,
  38.     
  39.     WindowMode: null,
  40.     
  41.     PostDataViewMode: 0,
  42.     
  43.     ContentViewMode: 0,
  44.     
  45.     XMLPrettyPrintXSLT: null,
  46.     
  47.     // constructor
  48.     init: function() 
  49.     {
  50.         this.FilteredRequests = new Array();
  51.         
  52.         this.HttpFoxService = Components.classes["@decoded.net/httpfox;1"].getService().wrappedJSObject;
  53.         
  54.         this.loadXMLPrettyPrintXSL();
  55.     },
  56.     
  57.     initGraphics: function(wmode) 
  58.     {
  59.         this.WindowMode = wmode;
  60.         this.clearRequestTree();
  61.         this.clearRequestInfoTabs();
  62.         this.selectionChange_ContentDisplayTypePretty();
  63.         this.selectionChange_PostDataDisplayTypePretty();
  64.         if (!this.HttpFoxService.Preferences.ShowDebugTab)
  65.         {
  66.             document.getElementById("hf_DebugTabHeader").collapsed = "true";
  67.             document.getElementById("hf_DebugTabHeader").disabled = "true";
  68.         }
  69.         
  70.         this.HttpFoxService.addController(this);
  71.         this.initFilteredRequests(this.HttpFoxService.Requests);
  72.         if (this.HttpFoxService.IsWatching) 
  73.         {
  74.             this.disableButton_startWatching();
  75.         }
  76.         this.RequestTree.setCurrentToNewest();
  77.         
  78.         if (this.WindowMode) 
  79.         {
  80.             this.HttpFoxService.HttpFoxWindow = this;
  81.             document.getElementById("hf_TopBarButton_Detach").collapsed = true;
  82.             document.getElementById("hf_TopBarButton_Detach").disabled = true;
  83.         }
  84.         
  85.     },
  86.     
  87.     loadXMLPrettyPrintXSL: function()
  88.     {
  89.         var xslDoc = document.implementation.createDocument("", "", null);
  90.         xslDoc.async = false;
  91.         
  92.         // default xsl from firefox
  93.         //xslDoc.load("chrome://global/content/xml/XMLPrettyPrint.xsl");
  94.         var test = xslDoc.load("chrome://httpfox/content/XMLPrettyPrint.xsl");
  95.         
  96.         var processor = new XSLTProcessor();
  97.         processor.importStylesheet(xslDoc);
  98.         this.XMLPrettyPrintXSLT = processor;
  99.     },
  100.     
  101.     cmd_hf_showAbout: function()
  102.     {
  103.         alert("HttpFox");
  104.     },
  105.     
  106.     //C BUTTON
  107.     onClickStatusIcon: function(event)
  108.     {
  109.         if (event.button != 0) 
  110.         {
  111.             return;
  112.         }
  113.         else 
  114.         {
  115.             this.cmd_hf_togglePanel();
  116.         }
  117.     },
  118.     
  119.     cmd_hf_close: function()
  120.     {
  121.         if (this.WindowMode)
  122.         {
  123.             // close button in detached window
  124.             window.close();
  125.         }
  126.         else
  127.         {
  128.             this.cmd_hf_togglePanel();
  129.         }
  130.     },
  131.     
  132.     //G
  133.     cmd_hf_togglePanel: function()
  134.     {
  135.         var HttpFoxPanel = document.getElementById("hf_PanelNormal");
  136.         var HttpFoxPanelSplitter = document.getElementById("hf_PanelSplitter");
  137.         
  138.         // if already opened detached, switch to opened window
  139.         if (this.switchToDetachedWindowIfOpened())
  140.         {
  141.             return;
  142.         }
  143.         
  144.         // if always open detached, open detached
  145.         if (this.HttpFoxService.Preferences.AlwaysOpenDetached)
  146.         {
  147.             this.cmd_hf_detach();
  148.             
  149.             return;
  150.         }
  151.         
  152.         this.togglePanel();
  153.     },
  154.     
  155.     //C INPUT
  156.     cmd_hf_quickFilterChanged: function() 
  157.     {
  158.         var sb = document.getElementById("hf_QuickFilterBox");
  159.         this.QuickFilterText = sb.value;
  160.         this.applyFilter();
  161.     },
  162.     
  163.     setFocus: function()
  164.     {
  165.         window.focus();
  166.     },
  167.     
  168.     //CG
  169.     applyFilter: function() 
  170.     {
  171.         this.FilteredRequests = new Array();
  172.         for (var i = 0; i < this.HttpFoxService.Requests.length; i++) 
  173.         {
  174.             if (this.HttpFoxService.Requests[i].Url.indexOf(this.QuickFilterText) != -1)
  175.             {
  176.                 // filter matched
  177.                 this.FilteredRequests.push(this.HttpFoxService.Requests[i]);
  178.             }
  179.         }
  180.         
  181.         this.clearRequestTree();
  182.         this.clearRequestInfoTabs();
  183.     },
  184.     
  185.     isAutoScroll: function()
  186.     {
  187.         return document.getElementById("hf_AutoScrollCheckbox").checked;
  188.     },
  189.     
  190.     filterRequest: function(parameterArray)
  191.     {
  192.         var request = parameterArray["p1"];
  193.         
  194.         if (request.Url.indexOf(this.QuickFilterText) != -1)
  195.         {
  196.             this.FilteredRequests.push(request);
  197.             
  198.             this.redrawRequestTreePlusOne();
  199.         }
  200.     },
  201.     
  202.     initFilteredRequests: function(requests)
  203.     {
  204.         for (var r in requests)
  205.         {
  206.             if (requests[r].Url.indexOf(this.QuickFilterText) != -1)
  207.             {
  208.                 this.FilteredRequests.push(requests[r]);
  209.                 this.redrawRequestTreePlusOne();
  210.             }
  211.         }
  212.     },
  213.     
  214.     cmd_hf_toggleWatching: function()
  215.     {
  216.         if (this.HttpFoxService.IsWatching)
  217.         {
  218.             this.cmd_hf_stopWatching();
  219.         }
  220.         else 
  221.         {
  222.             this.cmd_hf_startWatching();
  223.         }
  224.     },
  225.     
  226.     //C BUTTON (on all controllers)
  227.     cmd_hf_startWatching: function() 
  228.     {
  229.         if (!this.HttpFoxService.IsWatching)
  230.         {
  231.             this.HttpFoxService.startWatching();
  232.         }
  233.     
  234.         this.HttpFoxService.callControllerMethod("disableButton_startWatching");
  235.     },
  236.     
  237.     disableButton_startWatching: function()
  238.     {
  239.         document.getElementById("cmd_hf_startWatching").setAttribute('disabled', 'true');
  240.         document.getElementById("cmd_hf_stopWatching").removeAttribute('disabled');
  241.     },
  242.     
  243.     //C BUTTON (on all controllers)
  244.     cmd_hf_stopWatching: function() 
  245.     {
  246.         if (this.HttpFoxService.IsWatching)
  247.         {
  248.             this.HttpFoxService.stopWatching();
  249.         }
  250.         
  251.         this.HttpFoxService.callControllerMethod("disableButton_stopWatching");
  252.     },
  253.     
  254.     disableButton_stopWatching: function()
  255.     {
  256.         document.getElementById("cmd_hf_stopWatching").setAttribute('disabled', 'true');
  257.         document.getElementById("cmd_hf_startWatching").removeAttribute('disabled');
  258.     },
  259.     
  260.     //C BUTTON (on all controllers)
  261.     cmd_hf_clear: function()
  262.     {
  263.         this.HttpFoxService.clearRequests();
  264.         
  265.         this.HttpFoxService.callControllerMethod("clear");
  266.     },
  267.     
  268.     cmd_hf_detach: function() 
  269.     {
  270.         // switch to window if opened
  271.         if (this.switchToDetachedWindowIfOpened())
  272.         {
  273.             return;
  274.         }
  275.         
  276.         // if not, open new one
  277.         this.OpenInWindow();
  278.         
  279.         // close panel
  280.         this.closePanel();
  281.         
  282.         // command checked
  283.         document.getElementById("cmd_hf_togglePanel").setAttribute("checked", true);
  284.     },
  285.     
  286.     switchToDetachedWindowIfOpened: function()
  287.     {
  288.         var HttpFoxPanel = document.getElementById("hf_PanelNormal");
  289.         var HttpFoxPanelSplitter = document.getElementById("hf_PanelSplitter");
  290.         
  291.         // if already opened detached, switch to opened window
  292.         if (this.HttpFoxService.HttpFoxWindow)
  293.         {
  294.             if (!HttpFoxPanel.collapsed)
  295.             {
  296.                 // close open panel
  297.                 HttpFoxPanelSplitter.collapsed = HttpFoxPanel.collapsed = true;
  298.             }
  299.             
  300.             // window already open. switch to that
  301.             this.HttpFoxService.HttpFoxWindow.setFocus();
  302.             
  303.             // command checked
  304.             document.getElementById("cmd_hf_togglePanel").setAttribute("checked", true);
  305.             
  306.             return true;
  307.         }
  308.         
  309.         return false;
  310.     },
  311.     
  312.     closePanel: function()
  313.     {
  314.         var HttpFoxPanel = document.getElementById("hf_PanelNormal");
  315.         var HttpFoxPanelSplitter = document.getElementById("hf_PanelSplitter");
  316.         HttpFoxPanelSplitter.collapsed = HttpFoxPanel.collapsed = true;
  317.     },
  318.     
  319.     windowIsClosed: function()
  320.     {
  321.         // command checked
  322.         document.getElementById("cmd_hf_togglePanel").setAttribute("checked", false);
  323.     },
  324.     
  325.     togglePanel: function()
  326.     {
  327.         var HttpFoxPanel = document.getElementById("hf_PanelNormal");
  328.         var HttpFoxPanelSplitter = document.getElementById("hf_PanelSplitter");
  329.         
  330.         // normal panel toggle
  331.         HttpFoxPanelSplitter.collapsed = HttpFoxPanel.collapsed = (HttpFoxPanel.collapsed) ? false : true;
  332.         
  333.         // command checked
  334.         document.getElementById("cmd_hf_togglePanel").setAttribute("checked", !HttpFoxPanelSplitter.collapsed);
  335.     },
  336.     
  337.     clear: function()
  338.     {
  339.         this.FilteredRequests = new Array();
  340.  
  341.         this.clearRequestTree();
  342.         this.clearRequestInfoTabs();
  343.     },
  344.     
  345.     //G
  346.     clearRequestTree: function()
  347.     {
  348.         var treeElement = document.getElementById("hf_RequestTree");
  349.         if (treeElement) 
  350.         {
  351.             this.RequestTree = new HttpFoxTree(treeElement, this);
  352.         }
  353.     },
  354.     
  355.     //G
  356.     clearRequestInfoTabs: function()
  357.     {
  358.         // clear headers
  359.         this.clearTreeEntries("hf_RequestHeadersChildren");
  360.         this.clearTreeEntries("hf_ResponseHeadersChildren");
  361.         
  362.         // clear cookies
  363.         this.clearTreeEntries("hf_CookiesSentChildren");
  364.         this.clearTreeEntries("hf_CookiesReceivedChildren");
  365.         
  366.         // clear cache info
  367.         //this.clearTreeEntries("hf_CacheInfoChildren");
  368.         
  369.         // clear querystring
  370.         this.clearTreeEntries("hf_QueryStringChildren");
  371.         
  372.         // clear postdata
  373.         this.clearTreeEntries("hf_PostDataChildren");
  374.         document.getElementById("hf_PostDataRawOutput").value = "";
  375.         
  376.         // clear content
  377.         document.getElementById("hf_RawContentOutput").value = "";
  378.         
  379.         // clear debug
  380.         var debugPanel = document.getElementById("hf_DebugOutput");
  381.         debugPanel.contentDocument.body.innerHTML = "";
  382.     },
  383.     
  384.     //G
  385.     redrawRequestTreePlusOne: function()
  386.     {
  387.         this.RequestTree.invalidate();
  388.         var count = this.RequestTree.rowCount;
  389.         this.RequestTree.rowCountChanged(count, 1);
  390.     },
  391.     
  392.     //G
  393.     redrawRequestTree: function()
  394.     {
  395.         this.RequestTree.invalidate();
  396.     },
  397.     
  398.     //G
  399.     redrawRequestTreeRow: function(index)
  400.     {
  401.         if (typeof(index) == "object") {
  402.             index = index["p1"];
  403.         }
  404.         
  405.         if (this.RequestTree.TreeElement.currentIndex == index)
  406.         {
  407.             this.redrawRequestDetails();
  408.         }
  409.         
  410.         this.RequestTree.invalidateRow(index);
  411.     },
  412.     
  413.     redrawRequestDetails: function()
  414.     {
  415.         this.selectionChange_RequestTree();
  416.     },
  417.     
  418.     selectionChange_PostDataDisplayTypePretty: function() 
  419.     {
  420.         this.PostDataViewMode = 0;
  421.         document.getElementById("hf_PostDataPrettyBox").collapsed = false;
  422.         document.getElementById("hf_PostDataRawBox").collapsed = true;
  423.     },
  424.     
  425.     selectionChange_PostDataDisplayTypeRaw: function() 
  426.     {
  427.         this.PostDataViewMode = 1;
  428.         document.getElementById("hf_PostDataPrettyBox").collapsed = true;
  429.         document.getElementById("hf_PostDataRawBox").collapsed = false;
  430.     },
  431.     
  432.     selectionChange_ContentDisplayTypePretty: function() 
  433.     {
  434.         if (document.getElementById("hf_ContentRadioPretty").disabled)
  435.         {
  436.             return;
  437.         }
  438.         
  439.         this.ContentViewMode = 0;
  440.         document.getElementById("hf_PrettyContentOutput").collapsed = false;
  441.         document.getElementById("hf_RawContentOutput").collapsed = true;
  442.     },
  443.     
  444.     selectionChange_ContentDisplayTypeRaw: function() 
  445.     {
  446.         if (document.getElementById("hf_ContentRadioPretty").disabled)
  447.         {
  448.             return;
  449.         }
  450.         
  451.         this.ContentViewMode = 1;
  452.         document.getElementById("hf_PrettyContentOutput").collapsed = true;
  453.         document.getElementById("hf_RawContentOutput").collapsed = false;
  454.     },
  455.     
  456.     disableContentDisplayTypePrettyRadio: function()
  457.     {
  458.         document.getElementById("hf_ContentRadioGroup").selectedIndex = 1;
  459.         document.getElementById("hf_ContentRadioPretty").disabled = true;
  460.         document.getElementById("hf_ContentRadioGroup").disabled = true;
  461.         document.getElementById("hf_PrettyContentOutput").collapsed = true;
  462.         document.getElementById("hf_RawContentOutput").collapsed = false;
  463.     },
  464.     
  465.     enableContentDisplayTypePrettyRadio: function()
  466.     {
  467.         document.getElementById("hf_ContentRadioGroup").selectedIndex = this.ContentViewMode;
  468.         document.getElementById("hf_ContentRadioPretty").disabled = false;
  469.         document.getElementById("hf_ContentRadioGroup").disabled = false;
  470.         if (this.ContentViewMode == 0)
  471.         {
  472.             this.selectionChange_ContentDisplayTypePretty();
  473.         }
  474.         else
  475.         {
  476.             this.selectionChange_ContentDisplayTypeRaw();
  477.         }
  478.     },
  479.     
  480.     //G TABCLICK
  481.     selectionChange_RequestDetails: function() 
  482.     {
  483.         try
  484.         {
  485.             this.SelectedRequestDetailsTab = document.getElementById("hf_RequestDetailsTabs").selectedIndex;
  486.             
  487.             if (this.isSelectedTab_Debug() && !this.HttpFoxService.Preferences.ShowDebugTab) 
  488.             {
  489.                 document.getElementById("hf_RequestDetailsTabs").selectedIndex = 0;
  490.             }
  491.             
  492.             var contentPanel = document.getElementById("hf_RawContentOutput");
  493.             var currentRequest = this.RequestTree.getCurrent();
  494.             if (currentRequest && this.isSelectedTab_Content()) 
  495.             {
  496.                 if (currentRequest.isContentAvailable())  
  497.                 {
  498.                     // async
  499.                     this.showRawContentLoading();
  500.                     currentRequest.startGetRawContent(this);
  501.                 }
  502.                 else 
  503.                 {
  504.                     this.clearContentDisplay();
  505.                     this.showRawContentNotAvailable();
  506.                 }
  507.                 //if (currentRequest.getCachedResponse()) {
  508.                 //    contentPanel.value = currentRequest.getRawContent();
  509.                 //}
  510.                 //else {
  511.                 //    contentPanel.value = "BUSY / PROBLEM";
  512.                 //}
  513.                 //contentPanel.value = currentRequest.getRawContent();
  514.                 //contentPanel.value = currentRequest.getCachedResponse();
  515.             }
  516.             else 
  517.             {
  518.                 contentPanel.value = "";
  519.             }
  520.             
  521.             var debugPanel = document.getElementById("hf_DebugOutput");
  522.             if (currentRequest && this.isSelectedTab_Debug()) 
  523.             {
  524.                 debugPanel.contentDocument.body.innerHTML = this.getDebugInfoContent(currentRequest);
  525.             }
  526.             else 
  527.             {
  528.                 debugPanel.contentDocument.body.innerHTML = "";
  529.             }
  530.         }
  531.         catch(exc)
  532.         {}
  533.     },
  534.     
  535.     //G
  536.     selectionChange_RequestTree: function() 
  537.     {
  538.         var currentRequest = this.RequestTree.getCurrent();
  539.         
  540.         // update debug
  541.         var debugPanel = document.getElementById("hf_DebugOutput");
  542.         if (this.isSelectedTab_Debug()) 
  543.         {
  544.             debugPanel.contentDocument.body.innerHTML = this.getDebugInfoContent(currentRequest);
  545.         }
  546.         else 
  547.         {
  548.             debugPanel.contentDocument.body.innerHTML = "";
  549.         }
  550.         
  551.         // update cookie info
  552.         this.showCookieInfo(currentRequest);
  553.         
  554.         // update cache info
  555.         //this.showCacheInfo(currentRequest);
  556.         
  557.         // update post data info
  558.         this.showPostData(currentRequest);
  559.         
  560.         // update querystring info
  561.         this.showQueryStringParameters(currentRequest);
  562.         
  563.         // headers
  564.         this.showRequestHeaders(currentRequest);
  565.         this.showResponseHeaders(currentRequest);
  566.         
  567.         // update/get content
  568.         var contentPanel = document.getElementById("hf_RawContentOutput");
  569.         if (this.isSelectedTab_Content()) 
  570.         {
  571.             //net.decoded.utils.dumpall("curr-request", currentRequest);
  572.             //alert("avail.? ");
  573.             if (currentRequest.isContentAvailable())  {
  574.                 // async
  575.                 this.showRawContentLoading();
  576.                 currentRequest.startGetRawContent(this);
  577.                 
  578.                 /*if (currentRequest.getCachedResponse()) {
  579.                     contentPanel.value = currentRequest.getRawContent();
  580.                 }
  581.                 else {
  582.                     // one more time.
  583.                     if (currentRequest.getCachedResponse()) {
  584.                         contentPanel.value = currentRequest.getRawContent();
  585.                     }
  586.                     else {
  587.                         contentPanel.value = "BUSY / PROBLEM (try again)";
  588.                     }
  589.                 }*/
  590.             }
  591.             else {
  592.                 this.clearContentDisplay();
  593.                 this.showRawContentNotAvailable();
  594.             }
  595.             //contentPanel.value = currentRequest.getRawContent();
  596.         }
  597.         else 
  598.         {
  599.             contentPanel.value = "";
  600.         }
  601.     },
  602.     
  603.     clearContentDisplay: function()
  604.     {
  605.         document.getElementById("hf_PrettyContentOutput").contentDocument.body.innerHTML = "";
  606.         document.getElementById("hf_RawContentOutput").value = "";
  607.         document.getElementById("hf_ContentTypeLabel").value = "Type: ";
  608.         this.disableContentDisplayTypePrettyRadio();
  609.     },
  610.     
  611.     //G
  612.     showRawContent: function(status) 
  613.     {
  614.         var currentRequest = this.RequestTree.getCurrent();
  615.         var contentPanelRaw = document.getElementById("hf_RawContentOutput");
  616.         var contentPanelPretty = document.getElementById("hf_PrettyContentOutput");
  617.         
  618.         // clear first
  619.         this.clearContentDisplay();
  620.         
  621.         // display content-type
  622.         document.getElementById("hf_ContentTypeLabel").value = "Type: " + (currentRequest.ContentType ? currentRequest.ContentType : "");
  623.         
  624.         // not finished
  625.         if (status == -1)
  626.         {
  627.             // not finished
  628.             this.showRawContentNotFinished();
  629.             return;
  630.         }
  631.         
  632.         // error at getting content
  633.         if (status > 0)
  634.         {
  635.             // error
  636.             this.showRawContentError(status);
  637.             return;
  638.         }
  639.         
  640.         // fill raw content display
  641.         contentPanelRaw.value = currentRequest.Content;
  642.         
  643.         // try to fill pretty print content
  644.         if (net.decoded.utils.isContentTypeXml(currentRequest.ContentType))
  645.         {
  646.             // enable pretty
  647.             this.enableContentDisplayTypePrettyRadio();
  648.             
  649.             // xml (by mimetype definition)
  650.             this.getPrettyPrintXML(currentRequest.Content, "hf_PrettyContentOutput");
  651.             
  652.             // display if selected view
  653.             if (this.ContentViewMode == 0)
  654.             {
  655.                 this.selectionChange_ContentDisplayTypePretty();
  656.             }
  657.             
  658.             return;
  659.         }
  660.     },
  661.     
  662.     //G
  663.     showRawContentLoading: function() 
  664.     {
  665.         this.clearContentDisplay();
  666.         
  667.         document.getElementById("hf_RawContentOutput").value = "Loading...";
  668.     },
  669.     
  670.     showRawContentError: function(status) 
  671.     {
  672.         this.clearContentDisplay();
  673.         
  674.         document.getElementById("hf_RawContentOutput").value = "Error loading content (" + net.decoded.utils.nsResultErrors[status.toString(16)] + ")";
  675.     },
  676.     
  677.     showRawContentNotAvailable: function() 
  678.     {
  679.         this.clearContentDisplay();
  680.         
  681.         document.getElementById("hf_RawContentOutput").value = "Not available";
  682.     },
  683.     
  684.     showRawContentNotFinished: function() 
  685.     {
  686.         this.clearContentDisplay();
  687.         
  688.         document.getElementById("hf_RawContentOutput").value = "Not ready...";
  689.     },
  690.     
  691.     //G
  692.     isSelectedTab_Content: function()
  693.     {
  694.         if (this.SelectedRequestDetailsTab == 4)
  695.         {
  696.             return true;
  697.         }
  698.         return false;
  699.     },
  700.     
  701.     //G
  702.     isSelectedTab_Debug: function()
  703.     {
  704.         if (this.SelectedRequestDetailsTab == 5)
  705.         {
  706.             return true;
  707.         }
  708.         return false;
  709.     },
  710.     
  711.     //G
  712.     addHeaderRow: function(elementid, name, value)
  713.     {
  714.         var tree = document.getElementById(elementid);
  715.         var newRow = tree.appendChild(document.createElement('treeitem')).appendChild(document.createElement('treerow'));
  716.         newRow.appendChild(document.createElement('treecell')).setAttribute('label', name);
  717.         newRow.appendChild(document.createElement('treecell')).setAttribute('label', value);
  718.     },
  719.     
  720.     //G
  721.     addCookieRow: function(elementid, name, value, path, domain, expires)
  722.     {
  723.         var tree = document.getElementById(elementid);
  724.         var newRow = tree.appendChild(document.createElement('treeitem')).appendChild(document.createElement('treerow'));
  725.         newRow.appendChild(document.createElement('treecell')).setAttribute('label', name);
  726.         newRow.appendChild(document.createElement('treecell')).setAttribute('label', value);
  727.         newRow.appendChild(document.createElement('treecell')).setAttribute('label', path);
  728.         newRow.appendChild(document.createElement('treecell')).setAttribute('label', domain);
  729.         newRow.appendChild(document.createElement('treecell')).setAttribute('label', expires);
  730.     },
  731.     
  732.     //G
  733.     clearTreeEntries: function(elementid)
  734.     {
  735.         var tree = document.getElementById(elementid);
  736.         var items = tree.getElementsByTagName('treeitem');
  737.         while(items.length > 0)
  738.         {
  739.             tree.removeChild(items[0]);
  740.         }
  741.     },
  742.     
  743.     //G
  744.     showRequestHeaders: function(request)
  745.     {
  746.         this.clearTreeEntries("hf_RequestHeadersChildren");
  747.         
  748.         // request line
  749.         this.addHeaderRow("hf_RequestHeadersChildren", "(Request-Line)", request.RequestMethod + " " + request.URIPath + " HTTP/" + request.RequestProtocolVersion);
  750.         
  751.         for (i in request.RequestHeaders)
  752.         {
  753.             this.addHeaderRow("hf_RequestHeadersChildren", i, request.RequestHeaders[i]);
  754.         }
  755.  
  756.         for (i in request.PostDataHeaders) 
  757.         {
  758.             this.addHeaderRow("hf_RequestHeadersChildren", i, request.PostDataHeaders[i]);
  759.         }
  760.     },
  761.     
  762.     //G
  763.     showResponseHeaders: function(request)
  764.     {
  765.         this.clearTreeEntries("hf_ResponseHeadersChildren");
  766.  
  767.         // response status and text
  768.         if (request.ResponseHeaders != null)
  769.         {
  770.             this.addHeaderRow("hf_ResponseHeadersChildren", "(Status-Line)", "HTTP/" + request.ResponseProtocolVersion + " " + request.ResponseStatus + " " + request.ResponseStatusText);
  771.         }
  772.         
  773.         for (i in request.ResponseHeaders)
  774.         {
  775.             if (i == "Set-Cookie") 
  776.             {
  777.                 // split into original multiple header values
  778.                 var setCookieHeaders = request.ResponseHeaders[i].split("\n");
  779.                 for (u in setCookieHeaders) 
  780.                 {
  781.                     this.addHeaderRow("hf_ResponseHeadersChildren", i, setCookieHeaders[u]);
  782.                 }
  783.             }
  784.             else 
  785.             {
  786.                 this.addHeaderRow("hf_ResponseHeadersChildren", i, request.ResponseHeaders[i]);
  787.             }
  788.         }
  789.     },
  790.     
  791.     //G
  792.     showQueryStringParameters: function(request)
  793.     {
  794.         this.clearTreeEntries("hf_QueryStringChildren");
  795.         
  796.         if (request.QueryString == null)
  797.         {
  798.             this.addHeaderRow("hf_QueryStringChildren", "(none)", "(The URL does not contain a query string)");
  799.             return;
  800.         }
  801.         
  802.         for (i in request.QueryStringParameters)
  803.         {
  804.             this.addHeaderRow("hf_QueryStringChildren", net.decoded.utils.urlDecode(request.QueryStringParameters[i][0]), net.decoded.utils.urlDecode(request.QueryStringParameters[i][1]));
  805.         }
  806.     },
  807.     
  808.     //G
  809.     showCookieInfo: function(request)
  810.     {
  811.         this.clearTreeEntries("hf_CookiesSentChildren");
  812.         this.clearTreeEntries("hf_CookiesReceivedChildren");
  813.         
  814.         if (request.CookiesSent == null && request.CookiesReceived == null) 
  815.         {
  816.             // no cookies
  817.             return;
  818.         }
  819.         
  820.         for (i in request.CookiesSent)
  821.         {
  822.             this.addCookieRow("hf_CookiesSentChildren", request.CookiesSent[i]["name"], request.CookiesSent[i]["value"], (request.CookiesSent[i]["path"]) ? request.CookiesSent[i]["path"] : "", (request.CookiesSent[i]["domain"]) ? request.CookiesSent[i]["domain"] : "", (request.CookiesSent[i]["expires"]) ? net.decoded.utils.formatDateTime(request.CookiesSent[i]["expires"]) : "End Of Session");
  823.         }
  824.         
  825.         for (i in request.CookiesReceived)
  826.         {
  827.             this.addCookieRow("hf_CookiesReceivedChildren", request.CookiesReceived[i]["name"], request.CookiesReceived[i]["value"], request.CookiesReceived[i]["path"], (request.CookiesReceived[i]["domain"]) ? request.CookiesReceived[i]["domain"] : "", (request.CookiesReceived[i]["expires"]) ? request.CookiesReceived[i]["expires"] : "End Of Session");
  828.         }
  829.     },
  830.     
  831.     //G
  832.     showCacheInfo: function(request)
  833.     {
  834.         this.clearTreeEntries("hf_CacheInfoChildren");
  835.         
  836.         //TODO: REFACTOR
  837.         request.showCacheInfo();
  838.     },
  839.     
  840.     //G
  841.     showPostData: function(request)
  842.     {
  843.         if (this.PostDataViewMode == 0)
  844.         {
  845.             this.selectionChange_PostDataDisplayTypePretty();
  846.         }
  847.         else 
  848.         {
  849.             this.selectionChange_PostDataDisplayTypeRaw();
  850.         }
  851.         
  852.         // init
  853.         document.getElementById("hf_PostDataPretty").collapsed = true;
  854.         document.getElementById("hf_PostDataTree").collapsed = false;
  855.         
  856.         // fill raw data
  857.         if (request.IsPostDataTooBig)
  858.         {
  859.             document.getElementById("hf_PostDataRawOutput").value = "too big...";
  860.         }
  861.         else
  862.         {
  863.             document.getElementById("hf_PostDataRawOutput").value = request.PostData;
  864.         }
  865.         
  866.         // fill pretty data
  867.         var mimeLabel = document.getElementById("hf_PostDataMimeType");
  868.         mimeLabel.value = "Type: ";
  869.         this.clearTreeEntries("hf_PostDataChildren");
  870.         
  871.         if (request.PostData == null) {
  872.             this.addHeaderRow("hf_PostDataChildren", "(none)", "(This request contained no POST data)");
  873.             return;
  874.         }
  875.         
  876.         var ctypedisplay = "";
  877.         for (var y in request.PostDataHeaders)
  878.         {
  879.             if (y.toLowerCase() == "content-type")
  880.             {
  881.                 ctypedisplay = request.PostDataHeaders[y];
  882.             }
  883.         }
  884.         if (ctypedisplay == "")
  885.         {
  886.             for (var y in request.RequestHeaders)
  887.             {
  888.                 if (y.toLowerCase() == "content-type")
  889.                 {
  890.                     ctypedisplay = request.RequestHeaders[y];
  891.                 }
  892.             }
  893.         }
  894.         
  895.         mimeLabel.value = "Type: " + ctypedisplay;
  896.         
  897.         if (request.IsPostDataMIME) 
  898.         {
  899.             // mime post data
  900.             
  901.             for (i in request.PostDataMIMEParts)
  902.             {
  903.                 if (request.PostDataMIMEParts[i]["filename"] != null)
  904.                 {
  905.                     this.addHeaderRow("hf_PostDataChildren", 
  906.                         request.PostDataMIMEParts[i]["varname"], 
  907.                         request.PostDataMIMEParts[i]["filename"] + " " + request.PostDataMIMEParts[i]["ctype"]);
  908.                 }
  909.                 else 
  910.                 {
  911.                     this.addHeaderRow("hf_PostDataChildren", request.PostDataMIMEParts[i]["varname"], request.PostDataMIMEParts[i]["value"]);    
  912.                 }
  913.                 
  914.             }    
  915.         }
  916.         else if (request.PostDataParameters)
  917.         {
  918.             // standard url encoded post data
  919.             
  920.             for (i in request.PostDataParameters)
  921.             {
  922.                 if (request.PostDataParameters[i][0] != null && request.PostDataParameters[i][0] != "") 
  923.                 {
  924.                     this.addHeaderRow("hf_PostDataChildren", net.decoded.utils.urlDecode(request.PostDataParameters[i][0]), net.decoded.utils.urlDecode(request.PostDataParameters[i][1] != null ? request.PostDataParameters[i][1] : ""));    
  925.                 }
  926.                 
  927.             }
  928.         }
  929.         else
  930.         {
  931.             // raw content
  932.             document.getElementById("hf_PostDataPretty").collapsed = false;
  933.             document.getElementById("hf_PostDataTree").collapsed = true;
  934.             
  935.             // check if url parameter style
  936.             if (net.decoded.utils.isXml(request.PostData))
  937.             {
  938.                 this.getPrettyPrintXML(request.PostData, "hf_PostDataPretty");    
  939.             }
  940.             else 
  941.             {
  942.                 // just raw...
  943.                 document.getElementById("hf_PostDataPretty").contentDocument.body.innerHTML = request.PostData; 
  944.             }
  945.         }
  946.     },
  947.     
  948.     getPrettyPrintXML: function(xmlData, browserBoxId)
  949.     {
  950.         var parser = new DOMParser();
  951.         var doc = parser.parseFromString(xmlData, "text/xml");
  952.         
  953.         var HTMLOutput = this.XMLPrettyPrintXSLT.transformToFragment(doc, document);
  954.                 
  955.         var debugPanel = document.getElementById(browserBoxId);
  956.         debugPanel.contentDocument.body.innerHTML = "";
  957.         var importedNode = debugPanel.contentDocument.importNode(HTMLOutput, true);
  958.         debugPanel.contentDocument.body.appendChild(importedNode);
  959.         debugPanel.contentDocument.body.style.margin = 0;
  960.         debugPanel.contentDocument.body.style.padding = 0;
  961.     },
  962.     
  963.     //G
  964.     showDebugInfo: function(request)
  965.     {
  966.         var debugPanel = document.getElementById("hf_DebugOutput");
  967.         debugPanel.contentDocument.body.innerHTML = this.getDebugInfoContent(request);
  968.     },
  969.     
  970.     getDebugInfoContent: function(request)
  971.     {
  972.         var content = "";
  973.         content = "<div style=\"font-family:Tahoma,Verdana,Arial,sans-serif; font-size:11px;\">";
  974.         content += "<b>Url:</b> " + request.Url + "<br/>";
  975.         content += "<b>RequestMethod:</b> " + request.RequestMethod + "<br/>";
  976.         content += "<b>StartTimestamp:</b> " + request.StartTimestamp + "<br/>";
  977.         content += "<b>EndTimestamp:</b> " + request.EndTimestamp + "<br/>";
  978.         content += "<b>Loadflags: - request:</b> " + this.HttpFoxService.getStatusTextFromCode(this.HttpFoxService.HttpFoxStatusCodeType.LOADFLAGS_REQUEST, request.LoadFlags) + " (" + request.LoadFlags + ") <br/>";
  979.         content += "<b>Loadflags: - channel:</b> " + this.HttpFoxService.getStatusTextFromCode(this.HttpFoxService.HttpFoxStatusCodeType.LOADFLAGS_CHANNEL, request.LoadFlags) + " (" + request.LoadFlags + ") <br/>";
  980.         content += "<b>Loadflags: - caching:</b> " + this.HttpFoxService.getStatusTextFromCode(this.HttpFoxService.HttpFoxStatusCodeType.LOADFLAGS_CACHING, request.LoadFlags) + " (" + request.LoadFlags + ") <br/>";
  981.         content += "<b>IsFromCache:</b> " + request.IsFromCache + "<br/>";
  982.         content += "<b>BytesLoaded:</b> " + request.BytesLoaded + "<br/>";
  983.         content += "<b>BytesLoadedTotal:</b> " + request.BytesLoadedTotal + "<br/>";
  984.         content += "<b>ContentLength: </b>" + request.ContentLength + "<br/>";
  985.         content += "<b>ContentType: </b>" + request.ContentType + "<br/>";
  986.         content += "<b>ContentCharset: </b>" + request.ContentCharset + "<br/>";
  987.         content += "<b>ResponseStatus: </b>" + request.ResponseStatus + "<br/>";
  988.         content += "<b>ResponseStatusText: </b>" + request.ResponseStatusText + "<br/>";
  989.         
  990.         if (request.IsFromCache) {
  991.             content += "<br/>";
  992.             content += "<b>CacheToken:</b> " + request.CacheToken + "<br/>";
  993.             content += "<b>CacheKey:</b> " + request.CacheKey + "<br/>";
  994.             content += "<b>CacheAsFile:</b> " + request.CacheAsFile + "<br/>";
  995.             content += "<b>CacheFile:</b> " + request.CacheFile + "<br/>";
  996.         }
  997.         
  998.         // headers
  999.         for (i in request.RequestHeaders)
  1000.         {
  1001.             content += "<br/>";
  1002.             content += "<b>Request header:</b> " + i + " : " + request.RequestHeaders[i];
  1003.         }
  1004.         for (i in request.ResponseHeaders)
  1005.         {
  1006.             content += "<br/>";
  1007.             content += "<b>Response header:</b> " + i + " : " + request.ResponseHeaders[i];
  1008.         }
  1009.         
  1010.         content += "<br/>";
  1011.         
  1012.         for (i in request.RequestLog) 
  1013.         {
  1014.             content += "<br/>";
  1015.             content += "-> <b>EventLog " + i + ":</b> <br/>";
  1016.             content += "-------------------------------------------------------------------------<br/>";
  1017.             content += "<b> - Url: </b>" + request.RequestLog[i].Url + "<br/>";
  1018.             content += "<b> - ChannelStatus: </b>" + request.RequestLog[i].Status + "<br/>";
  1019.             content += "<b> - Statuscode: </b>" + request.RequestLog[i].ResponseStatus + "<br/>";
  1020.             content += "<b> - Timestamp: </b>" + request.RequestLog[i].Timestamp + "<br/>";
  1021.             content += "<b> - HttpFox starttime: </b>" + request.HttpFox.StartTime + "<br/>";
  1022.             //content += "- relative timestamp: " + net.decoded.utils.formatTime(new Date(this.RequestLog[i].Timestamp.getTime() - this.HttpFox.StartTime.getTime())) + "<br/>";
  1023.             content += "<b> - IsFromCache: </b>" + request.RequestLog[i].IsFromCache + "<br/>";
  1024.             content += "<b> - IsPending: </b>" + request.RequestLog[i].IsPending + "<br/>";
  1025.             content += "<b> - BytesLoaded: </b>" + request.RequestLog[i].BytesLoaded + "<br/>";
  1026.             content += "<b> - BytesLoadedTotal: </b>" + request.RequestLog[i].BytesLoadedTotal + "<br/>";
  1027.             content += "<b> - ContentLength: </b>" + request.RequestLog[i].ContentLength + "<br/>";
  1028.             content += "<b> - ContentType: </b>" + request.RequestLog[i].ContentType + "<br/>";
  1029.             content += "<b> - ContentCharset: </b>" + request.RequestLog[i].ContentCharset + "<br/>";
  1030.             content += "<b> - EventSource: </b>" + this.HttpFoxService.getEventSourceName(request.RequestLog[i].EventSource) + "<br/>";
  1031.             content += "<b> - EventSourceData: </b><br/>";
  1032.             for (u in request.RequestLog[i].EventSourceData)
  1033.             {
  1034.                 if ((request.RequestLog[i].EventSource == this.HttpFoxService.HttpFoxEventSourceType.EVENTSINK_ON_STATUS || 
  1035.                     request.RequestLog[i].EventSource == this.HttpFoxService.HttpFoxEventSourceType.WEBPROGRESS_ON_STATUS_CHANGED)
  1036.                     && u == "status") 
  1037.                 {
  1038.                     content += "<b> -- " + u + ": </b>" + this.HttpFoxService.getStatusTextFromCode(this.HttpFoxService.HttpFoxStatusCodeType.SOCKETTRANSPORT, request.RequestLog[i].EventSourceData[u]) + "<br/>";
  1039.                 }
  1040.                 else if (request.RequestLog[i].EventSource == this.HttpFoxService.HttpFoxEventSourceType.WEBPROGRESS_ON_SECURITY_CHANGED && u == "state") 
  1041.                 {
  1042.                     content += "<b> -- " + u + " - security: </b>" + this.HttpFoxService.getStatusTextFromCode(this.HttpFoxService.HttpFoxStatusCodeType.WEBPROGRESS_SECURITY, request.RequestLog[i].EventSourceData[u]) + "<br/>";
  1043.                     content += "<b> -- " + u + " - strength: </b>" + this.HttpFoxService.getStatusTextFromCode(this.HttpFoxService.HttpFoxStatusCodeType.WEBPROGRESS_SECURITY_STRENGTH, request.RequestLog[i].EventSourceData[u]) + "<br/>";
  1044.                 }
  1045.                 else if (request.RequestLog[i].EventSource == this.HttpFoxService.HttpFoxEventSourceType.WEBPROGRESS_ON_STATE_CHANGED && u == "flags") 
  1046.                 {
  1047.                     content += "<b> -- " + u + " - transition: </b>" + this.HttpFoxService.getStatusTextFromCode(this.HttpFoxService.HttpFoxStatusCodeType.WEBPROGRESS_TRANSITION, request.RequestLog[i].EventSourceData[u]) + "<br/>";
  1048.                     content += "<b> -- " + u + " - type: </b>" + this.HttpFoxService.getStatusTextFromCode(this.HttpFoxService.HttpFoxStatusCodeType.WEBPROGRESS_TYPE, request.RequestLog[i].EventSourceData[u]) + "<br/>";
  1049.                     content += "<b> -- " + u + " - modifier: </b>" + this.HttpFoxService.getStatusTextFromCode(this.HttpFoxService.HttpFoxStatusCodeType.WEBPROGRESS_MODIFIER, request.RequestLog[i].EventSourceData[u]) + "<br/>";
  1050.                     content += "<b> -- " + u + " - security: </b>" + this.HttpFoxService.getStatusTextFromCode(this.HttpFoxService.HttpFoxStatusCodeType.WEBPROGRESS_SECURITY, request.RequestLog[i].EventSourceData[u]) + "<br/>";
  1051.                     content += "<b> -- " + u + " - strength: </b>" + this.HttpFoxService.getStatusTextFromCode(this.HttpFoxService.HttpFoxStatusCodeType.WEBPROGRESS_SECURITY_STRENGTH, request.RequestLog[i].EventSourceData[u]) + "<br/>";
  1052.                 }
  1053.                 else if (request.RequestLog[i].EventSource == this.HttpFoxService.HttpFoxEventSourceType.WEBPROGRESS_ON_LOCATION_CHANGED && u == "uri") 
  1054.                 {
  1055.                     content += "<b> -- " + u + ": </b>" + request.RequestLog[i].EventSourceData[u].asciiSpec + "<br/>";
  1056.                 }
  1057.                 else 
  1058.                 {
  1059.                     content += "<b> -- " + u + ": </b>" + request.RequestLog[i].EventSourceData[u] + "<br/>";
  1060.                 }
  1061.             }
  1062.             content += "<br/>";
  1063.         }
  1064.         
  1065.         content += "</div>";
  1066.         return content;
  1067.     },
  1068.     
  1069.     //G
  1070.     getCurrentInfoTreeElement: function()
  1071.     {
  1072.         switch(this.SelectedRequestDetailsTab)
  1073.         {
  1074.             case 0:
  1075.                 return "hf_RequestHeadersTree" + ";" + "hf_ResponseHeadersTree";
  1076.  
  1077.             case 1:
  1078.                 return "hf_CookiesSentTree" + ";" + "hf_CookiesReceivedTree";
  1079.                 
  1080.             //case 2:
  1081.                 //return "hf_CacheInfoTree";
  1082.                 
  1083.             case 2:
  1084.                 return "hf_QueryStringTree";
  1085.                 
  1086.             case 3:
  1087.                 return "hf_PostDataTree";
  1088.                 
  1089.             default:
  1090.                 return "";
  1091.         }
  1092.     },
  1093.     
  1094.     //G
  1095.     // context menu stuff
  1096.     updateRequestContextMenu: function(event) 
  1097.     {
  1098.         var row = {};
  1099.         var column = {};
  1100.         var part = {};
  1101.         if (event.currentTarget.id == "hf_RequestTreeContextMenu")
  1102.         {
  1103.             var tree = this.RequestTree.TreeElement;
  1104.             var boxobject = tree.boxObject;
  1105.             var menu = document.getElementById("hf_RequestTreeContextMenu");
  1106.             
  1107.             boxobject.QueryInterface(Components.interfaces.nsITreeBoxObject);
  1108.             boxobject.getCellAt(event.clientX, event.clientY, row, column, part);
  1109.         }
  1110.         else 
  1111.         {
  1112.             var infoTreeIds = this.getCurrentInfoTreeElement().split(";");
  1113.             var tree;
  1114.             var boxobject;
  1115.             var menu = document.getElementById("hf_RequestDetailsContextMenu");
  1116.             for (i in infoTreeIds)
  1117.             {
  1118.                 row = {};
  1119.                 column = {};
  1120.                 tree = document.getElementById(infoTreeIds[i]);
  1121.                 boxobject = tree.boxObject;
  1122.                 boxobject.QueryInterface(Components.interfaces.nsITreeBoxObject);
  1123.                 boxobject.getCellAt(event.clientX, event.clientY, row, column, part);
  1124.                 if (column.value != null) {
  1125.                     // tree found
  1126.                     break;
  1127.                 }
  1128.             }
  1129.         }
  1130.         
  1131.         // set current tree
  1132.         this.currentContextTree = tree;
  1133.         
  1134.         if (column.value != null) 
  1135.         {
  1136.             // column and row found. show those two entries
  1137.             var celltext = tree.view.getCellText(row.value, tree.columns.getColumnAt(column.value.index));
  1138.             this.currentCellText = celltext;
  1139.             
  1140.             // copy cell
  1141.             menu.firstChild.setAttribute("hidden" , false);
  1142.             menu.firstChild.setAttribute("disabled", false);
  1143.             menu.firstChild.setAttribute("label", "Copy '"+ celltext + "'");
  1144.             
  1145.             // copy row
  1146.             menu.firstChild.nextSibling.setAttribute("hidden" , false);
  1147.             menu.firstChild.nextSibling.setAttribute("disabled", false);
  1148.         } 
  1149.         else 
  1150.         {
  1151.             //just show copy all rows
  1152.             this.currentCellText = null;
  1153.  
  1154.             // hide copy cell
  1155.             menu.firstChild.setAttribute("hidden" , true);
  1156.             menu.firstChild.setAttribute("disabled", true);
  1157.             
  1158.             // hide copy row
  1159.             menu.firstChild.nextSibling.setAttribute("hidden" , true);
  1160.             menu.firstChild.nextSibling.setAttribute("disabled", true);
  1161.         }
  1162.     },
  1163.     
  1164.     //G
  1165.     Clipboard_CopyTreeRowCell: function() 
  1166.     {
  1167.         if (this.currentCellText != null) 
  1168.         {
  1169.             net.decoded.utils.toClipboard(this.currentCellText);
  1170.         }
  1171.     },
  1172.     
  1173.     //G
  1174.     Clipboard_CopyTreeRow: function() 
  1175.     {
  1176.         if (this.currentContextTree != null) 
  1177.         {
  1178.             var copyString = "";
  1179.             for (var i = 0; i < this.currentContextTree.columns.count; i++) 
  1180.             {
  1181.                 copyString += this.currentContextTree.view.getCellText(this.currentContextTree.currentIndex, this.currentContextTree.columns.getColumnAt(i));
  1182.                 if (i < this.currentContextTree.columns.count - 1) 
  1183.                 {
  1184.                     copyString += "\t";
  1185.                 }
  1186.             }
  1187.             net.decoded.utils.toClipboard(copyString);
  1188.         }
  1189.     },
  1190.     
  1191.     //G
  1192.     Clipboard_CopyTreeAllRows: function() 
  1193.     {
  1194.         if (this.currentContextTree != null) 
  1195.         {
  1196.             var copyString = "";
  1197.             var rowCount = this.currentContextTree.view.rowCount;
  1198.             for (var u = 0; u < rowCount; u++) 
  1199.             {
  1200.                 for (var i = 0; i < this.currentContextTree.columns.count; i++) 
  1201.                 {
  1202.                     copyString += this.currentContextTree.view.getCellText(u, this.currentContextTree.columns.getColumnAt(i));
  1203.                     if (i < this.currentContextTree.columns.count - 1) 
  1204.                     {
  1205.                         copyString += "\t";
  1206.                     }
  1207.                 }
  1208.                 if (u < rowCount - 1) 
  1209.                 {
  1210.                     copyString += "\n";
  1211.                 }
  1212.             }
  1213.             net.decoded.utils.toClipboard(copyString);
  1214.         }
  1215.     },
  1216.     
  1217.     //G
  1218.     OpenInWindow: function()
  1219.     {
  1220.         net.decoded.utils.openWindow("HttpFox", "chrome://httpfox/content/HttpFoxWindow.xul", "", null);
  1221.     },
  1222.     
  1223.     OpenOptions: function()
  1224.     {
  1225.         openDialog("chrome://httpfox/content/HttpFoxOptions.xul", "HttpFox Options", "", null);
  1226.     }
  1227.  
  1228. }
  1229.  
  1230. var HttpFox = new HttpFoxController();
  1231.  
  1232. function shutdownHttpFox()
  1233. {
  1234.     HttpFox.clear();
  1235.     //HttpFox.cmd_stopWatching();
  1236.  
  1237.     HttpFox.HttpFoxService.removeController(HttpFox);
  1238.     
  1239.     if (HttpFox.WindowMode)
  1240.     {
  1241.         HttpFox.HttpFoxService.HttpFoxWindow = null;
  1242.         HttpFox.HttpFoxService.windowIsClosed();
  1243.     }
  1244.     
  1245.     HttpFox = null;
  1246. }